package com.winning.pmph.schedule;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;
import com.winning.pmph.entity.Book;
import com.winning.pmph.entity.BookCategory;
import com.winning.pmph.entity.TZhipinXinxi;
import com.winning.pmph.entity.Tag;
import com.winning.pmph.service.BookCategoryService;
import com.winning.pmph.service.BookService;
import com.winning.pmph.service.TZhipinXinxiService;
import com.winning.pmph.service.TagService;
import com.winning.pmph.utils.Const;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Component
@ConditionalOnProperty(prefix = "scheduling", name = "enabled")
public class BookZhipinXinxiSchedule {
    @Resource
    private BookCategoryService bookCategoryService;
    @Resource
    private TZhipinXinxiService tZhipinXinxiService;
    @Resource
    private BookService bookService;
    @Resource
    private TagService tagService;

    /**
     * 根据ISBN号查询分类信息
     *
     * @param bookCategory
     * @param tagCodeMap
     * @return
     */
    public static JSONArray selectCategoryByIsbn(BookCategory bookCategory, Map<String, Tag> tagCodeMap) {
        JSONArray category = new JSONArray();
        if (StringUtils.isNotBlank(bookCategory.getZhipinyijifenleibianhao())) {
            category.add(tagCodeMap.get(bookCategory.getZhipinyijifenleibianhao()));
        } else if (StringUtils.isNotBlank(bookCategory.getZhipinerjifenleibianhao())) {
            category.add(tagCodeMap.get(bookCategory.getZhipinerjifenleibianhao()));
        } else if (StringUtils.isNotBlank(bookCategory.getZhipinsanjifenleibianhao())) {
            category.add(tagCodeMap.get(bookCategory.getZhipinsanjifenleibianhao()));
        } else if (StringUtils.isNotBlank(bookCategory.getZhipinsijifenleibianhao())) {
            category.add(tagCodeMap.get(bookCategory.getZhipinsijifenleibianhao()));
        }
        return category;
    }

    //@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨一点启动定时任务
    public void schedule() {
        log.info("启动定时任务, 同步修改制品信息");
        log.info("制品定时任务时间: " + LocalDateTime.now().toString());
        // 同步逻辑  图书分类在知识平台没有修改入口  只能修改挂载信息
        // 暂时线下同步制品信息数据
        // 从制品同步3个字段,分类,图书简介,纸书价格
        // 先比较分类信息是否修改
        List<TZhipinXinxi> remoteTZhipinXinxiList = tZhipinXinxiService.lambdaQuery().isNotNull(TZhipinXinxi::getBiaozhunshuhao).ne(TZhipinXinxi::getBiaozhunshuhao, "978-7-117-12845-2").list();
        Map<String, TZhipinXinxi> remoteZhipinXinxiMap = remoteTZhipinXinxiList.stream().collect(Collectors.toMap(TZhipinXinxi::getBiaozhunshuhao, Function.identity()));
        Map<String, BookCategory> localTZhipinXinxiMap = bookCategoryService.lambdaQuery().isNotNull(BookCategory::getBiaozhunshuhao).list().stream().collect(Collectors.toMap(BookCategory::getBiaozhunshuhao, Function.identity()));
        Map<String, Book> bookMap = bookService.lambdaQuery().isNotNull(Book::getIsbn).in(Book::getStatus, Book.BOOK_STATUS_UNPUBLISHED, Book.BOOK_STATUS_PUBLISHED).list().stream().collect(Collectors.toMap(Book::getIsbn, Function.identity()));
        ;
        // 修改分类信息
        syncCategory(Maps.newHashMap(remoteZhipinXinxiMap), Maps.newHashMap(localTZhipinXinxiMap), bookMap);
        // 修改图书简介
        syncSummary(Maps.newHashMap(remoteZhipinXinxiMap), Maps.newHashMap(localTZhipinXinxiMap), bookMap);
        // 同步纸书价格
        syncBprice(Maps.newHashMap(remoteZhipinXinxiMap), bookMap);
        // 更新bookcategory表为最新的制品信息表,先删除
        bookCategoryService.remove(Wrappers.lambdaQuery(BookCategory.class));
        bookCategoryService.saveBatch(JSON.parseArray(JSON.toJSONString(remoteTZhipinXinxiList), BookCategory.class));
    }

    /**
     * 同步分类信息
     *
     * @param remoteZhipinXinxiMap
     * @param localTZhipinXinxiMap
     */
    private void syncCategory(Map<String, TZhipinXinxi> remoteZhipinXinxiMap, Map<String, BookCategory> localTZhipinXinxiMap, Map<String, Book> bookMap) {
        for (Map.Entry<String, TZhipinXinxi> entry : remoteZhipinXinxiMap.entrySet()) {
            remoteZhipinXinxiMap.put(entry.getKey(), new TZhipinXinxi(entry.getValue().getBiaozhunshuhao(),
                    entry.getValue().getZhipinyijifenleibianhao(),
                    entry.getValue().getZhipinyijifenlei(), entry.getValue().getZhipinerjifenleibianhao(),
                    entry.getValue().getZhipinerjifenlei(), entry.getValue().getZhipinsanjifenleibianhao(),
                    entry.getValue().getZhipinsanjifenlei(), entry.getValue().getZhipinsijifenleibianhao(),
                    entry.getValue().getZhipinsijifenlei()));
        }

        for (Map.Entry<String, BookCategory> entry : localTZhipinXinxiMap.entrySet()) {
            localTZhipinXinxiMap.put(entry.getKey(), new BookCategory(entry.getValue().getBiaozhunshuhao(),
                    entry.getValue().getZhipinyijifenleibianhao(),
                    entry.getValue().getZhipinyijifenlei(), entry.getValue().getZhipinerjifenleibianhao(),
                    entry.getValue().getZhipinerjifenlei(), entry.getValue().getZhipinsanjifenleibianhao(),
                    entry.getValue().getZhipinsanjifenlei(), entry.getValue().getZhipinsijifenleibianhao(),
                    entry.getValue().getZhipinsijifenlei()));
        }

        // 1,先对比远端分类信息与本地分类信息,找出增量数据,暂时不考虑远端删除
        List<TZhipinXinxi> incrementList = new ArrayList<>();
        for (Map.Entry<String, TZhipinXinxi> remoteEntry : remoteZhipinXinxiMap.entrySet()) {
            BookCategory local = localTZhipinXinxiMap.get(remoteEntry.getKey());
            // 增量数据
            if (!local.toString().equals(remoteEntry.getValue().toString())) {
                incrementList.add(remoteEntry.getValue());
            }
        }
        // 说明本地和远端一样,则无需做任何修改
        if (CollectionUtils.isEmpty(incrementList)) {
            log.info("知识平台制品分类信息和远端制品分类信息一致,定时任务结束");
            return;
        }

        // 2,远端修改了图书分类信息,同步到知识平台的图书分类信息
        List<Tag> tagList = tagService.lambdaQuery().eq(Tag::getRootId, Const.TAG_BOOK_ROOT_ID).list();
        // 更新制品信息后的最新的图书分类
        Map<String, Tag> newTagCodeMap = tagList.stream().collect(Collectors.toMap(Tag::getTagCode, Function.identity()));
        // 未更新制品信息的图书分类,方便后面判断图书分类是否在图书模块编辑了
        Map<String, Tag> tagCodeMap = tagList.stream().collect(Collectors.toMap(Tag::getTagCode, Function.identity()));
        Map<String, List<Tag>> tagParentIdMap = tagList.stream().collect(Collectors.groupingBy(Tag::getParentId));
        incrementList.forEach(increment -> {
            if (StringUtils.isNotBlank(increment.getZhipinyijifenleibianhao())) {
                Tag newTag = newTagCodeMap.get(increment.getZhipinyijifenleibianhao());
                if (Objects.isNull(newTag)) {
                    // 说明新增了分类
                    newTag = new Tag(IdWorker.getIdStr(), increment.getZhipinyijifenlei(), Const.TAG_BOOK_ROOT_ID, increment.getZhipinyijifenleibianhao(),
                            2, tagParentIdMap.getOrDefault(Const.TAG_BOOK_ROOT_ID, Lists.newArrayList()).size(), Const.TAG_BOOK_ROOT_ID, false);
                    tagParentIdMap.get(Const.TAG_BOOK_ROOT_ID).add(newTag);
                } else {
                    // 可能修改了分类名字
                    newTag.setName(increment.getZhipinyijifenlei());
                }
                newTagCodeMap.put(increment.getZhipinyijifenleibianhao(), newTag);
                tagService.saveOrUpdate(newTag);
            } else if (StringUtils.isNotBlank(increment.getZhipinerjifenleibianhao())) {
                Tag newTag = newTagCodeMap.get(increment.getZhipinerjifenleibianhao());
                if (Objects.isNull(newTag)) {
                    // 说明新增了分类
                    String parentId = newTagCodeMap.get(increment.getZhipinyijifenleibianhao()).getId();
                    newTag = new Tag(IdWorker.getIdStr(), increment.getZhipinerjifenlei(), parentId, increment.getZhipinerjifenleibianhao(),
                            3, tagParentIdMap.getOrDefault(parentId, Lists.newArrayList()).size(), Const.TAG_BOOK_ROOT_ID, false);
                    tagParentIdMap.get(parentId).add(newTag);
                } else {
                    // 可能修改了分类名字
                    newTag.setName(increment.getZhipinerjifenlei());
                }
                newTagCodeMap.put(increment.getZhipinerjifenleibianhao(), newTag);
            } else if (StringUtils.isNotBlank(increment.getZhipinsanjifenleibianhao())) {
                Tag newTag = newTagCodeMap.get(increment.getZhipinsanjifenleibianhao());
                if (Objects.isNull(newTag)) {
                    // 说明新增了分类
                    String parentId = newTagCodeMap.get(increment.getZhipinerjifenleibianhao()).getId();
                    newTag = new Tag(IdWorker.getIdStr(), increment.getZhipinsanjifenlei(), parentId, increment.getZhipinsanjifenleibianhao(),
                            4, tagParentIdMap.getOrDefault(parentId, Lists.newArrayList()).size(), Const.TAG_BOOK_ROOT_ID, false);
                    tagParentIdMap.get(parentId).add(newTag);
                } else {
                    // 可能修改了分类名字
                    newTag.setName(increment.getZhipinsanjifenlei());
                }
                newTagCodeMap.put(increment.getZhipinsanjifenleibianhao(), newTag);
            } else if (StringUtils.isNotBlank(increment.getZhipinsijifenleibianhao())) {
                Tag newTag = newTagCodeMap.get(increment.getZhipinsijifenleibianhao());
                if (Objects.isNull(newTag)) {
                    // 说明新增了分类
                    String parentId = newTagCodeMap.get(increment.getZhipinsanjifenleibianhao()).getId();
                    newTag = new Tag(IdWorker.getIdStr(), increment.getZhipinsijifenlei(), parentId, increment.getZhipinsijifenleibianhao(),
                            5, tagParentIdMap.getOrDefault(parentId, Lists.newArrayList()).size(), Const.TAG_BOOK_ROOT_ID, false);
                    tagParentIdMap.get(parentId).add(newTag);
                } else {
                    // 可能修改了分类名字
                    newTag.setName(increment.getZhipinsijifenlei());
                }
                newTagCodeMap.put(increment.getZhipinsijifenleibianhao(), newTag);
            }
        });

        // 3,对比图书分类和本地制品信息分类,如果一致,则说明本地图书信息分类未修改过,此时以远端分类信息为准
        // 如果本地图书分类信息修改过,则以本地修改为准
        // 对比图书的分类和本地的分类,查看是否在知识管理平台修改过图书分类

        Map<String, JSONArray> localCategoryMap = Maps.newHashMap();
        for (Map.Entry<String, BookCategory> entry : localTZhipinXinxiMap.entrySet()) {
            localCategoryMap.put(entry.getKey(), selectCategoryByIsbn(entry.getValue(), tagCodeMap));
        }

        for (Map.Entry<String, Book> bookEntry : bookMap.entrySet()) {
            JSONArray localCategory = localCategoryMap.get(bookEntry.getKey());
            // 说明图书分类信息已修改,以当前图书分类信息为准
            if (!bookEntry.getValue().getCategory().equals(localCategory)) {
                continue;
            }
            // 根据ISBN号在最新的制品表里查不到
            TZhipinXinxi tZhipinXinxi = remoteZhipinXinxiMap.get(bookEntry.getValue().getIsbn());
            if (Objects.isNull(tZhipinXinxi)) {
                continue;
            }
            // 修改图书分类信息
            bookEntry.getValue().setCategory(selectNewCategoryByIsbn(tZhipinXinxi, newTagCodeMap));
            bookService.updateById(bookEntry.getValue());
        }
        // 更新图书分类信息
        tagService.saveOrUpdateBatch(newTagCodeMap.values());
    }

    /**
     * 根据ISBN号查询最新的分类信息
     *
     * @param tZhipinXinxi
     * @param newTagCodeMap
     * @return
     */
    private JSONArray selectNewCategoryByIsbn(TZhipinXinxi tZhipinXinxi, Map<String, Tag> newTagCodeMap) {
        JSONArray category = new JSONArray();
        if (StringUtils.isNotBlank(tZhipinXinxi.getZhipinyijifenleibianhao())) {
            category.add(newTagCodeMap.get(tZhipinXinxi.getZhipinyijifenleibianhao()));
        } else if (StringUtils.isNotBlank(tZhipinXinxi.getZhipinerjifenleibianhao())) {
            category.add(newTagCodeMap.get(tZhipinXinxi.getZhipinerjifenleibianhao()));
        } else if (StringUtils.isNotBlank(tZhipinXinxi.getZhipinsanjifenleibianhao())) {
            category.add(newTagCodeMap.get(tZhipinXinxi.getZhipinsanjifenleibianhao()));
        } else if (StringUtils.isNotBlank(tZhipinXinxi.getZhipinsijifenleibianhao())) {
            category.add(newTagCodeMap.get(tZhipinXinxi.getZhipinsijifenleibianhao()));
        }
        return category;
    }

    private void syncSummary(Map<String, TZhipinXinxi> remoteZhipinXinxiMap, Map<String, BookCategory> localTZhipinXinxiMap, Map<String, Book> bookMap) {
        for (Map.Entry<String, TZhipinXinxi> entry : remoteZhipinXinxiMap.entrySet()) {
            remoteZhipinXinxiMap.put(entry.getKey(), new TZhipinXinxi(entry.getValue().getNeirongtiyao()));
        }

        for (Map.Entry<String, BookCategory> entry : localTZhipinXinxiMap.entrySet()) {
            localTZhipinXinxiMap.put(entry.getKey(), new BookCategory(entry.getValue().getNeirongtiyao()));
        }

        // 1,先对比远端简介信息与本地简介信息,找出增量数据,暂时不考虑远端删除
        List<TZhipinXinxi> incrementList = new ArrayList<>();
        for (Map.Entry<String, TZhipinXinxi> remoteEntry : remoteZhipinXinxiMap.entrySet()) {
            BookCategory local = localTZhipinXinxiMap.get(remoteEntry.getKey());
            // 增量数据
            if (!local.toString().equals(remoteEntry.getValue().toString())) {
                incrementList.add(remoteEntry.getValue());
            }
        }
        // 说明本地和远端一样,则无需做任何修改
        if (CollectionUtils.isEmpty(incrementList)) {
            log.info("知识平台制品简介信息和远端制品简介信息一致,定时任务结束");
            return;
        }

        // 2,对比图书简介和本地制品简介信息,如果一致,则说明本地图书信息分类未修改过,此时以远端简介为准
        // 如果本地图书简介信息修改过,则以本地修改为准
        // 对比图书的简介和本地的简介,查看是否在知识管理平台修改过图书简介

        Map<String, String> localSummaryMap = Maps.newHashMap();
        for (Map.Entry<String, BookCategory> entry : localTZhipinXinxiMap.entrySet()) {
            localSummaryMap.put(entry.getKey(), entry.getValue().getNeirongtiyao());
        }

        for (Map.Entry<String, Book> bookEntry : bookMap.entrySet()) {
            String localSummary = localSummaryMap.get(bookEntry.getKey());
            // 说明图书简介信息已修改,以当前图书简介信息为准
            if (!bookEntry.getValue().getMetadata().getString("summary").equals(localSummary)) {
                continue;
            }
            // 根据ISBN号在最新的制品表里查不到
            TZhipinXinxi tZhipinXinxi = remoteZhipinXinxiMap.get(bookEntry.getValue().getIsbn());
            if (Objects.isNull(tZhipinXinxi)) {
                continue;
            }
            // 修改图书简介信息
            bookEntry.getValue().getMetadata().put("summary", tZhipinXinxi.getNeirongtiyao());
            bookService.updateById(bookEntry.getValue());
        }
    }

    private void syncBprice(Map<String, TZhipinXinxi> remoteZhipinXinxiMap, Map<String, Book> bookMap) {
        // 当纸书价格为空时,更新纸书价格
        for (Map.Entry<String, Book> bookEntry : bookMap.entrySet()) {
            if (!Const.BOOK_TYPE_INCREASE.equals(bookEntry.getValue().getBookType())) {
                if (bookEntry.getValue().getMetadata().getJSONObject("Price").getDouble("B_price") == 0.00 && Objects.nonNull(remoteZhipinXinxiMap.get(bookEntry.getKey()))) {
                    // 更新纸书价格
                    bookEntry.getValue().getMetadata().getJSONObject("Price").put("B_price", remoteZhipinXinxiMap.get(bookEntry.getKey()).getZhipindingjia());
                    bookService.updateById(bookEntry.getValue());
                }
            }
        }

    }
}
